package com.zbs.framework.dao.rolefunction.service.impl;

import com.zbs.framework.common.utils.ErrorAssert;
import com.zbs.framework.dao.rolefunction.entity.RoleFunction;
import com.zbs.framework.dao.rolefunction.repository.RoleFunctionRepository;
import com.zbs.framework.dao.rolefunction.service.RoleFunctionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Zbs
 * 2019-04-28 11:38
 */
@Service
@Transactional
public class RoleFunctionServiceImpl implements RoleFunctionService {

    @Autowired
    private RoleFunctionRepository roleFunctionRepository;

    @Override
    
    public void editRoleFunctions(Integer roleId, List<Long> functionIds) {
        // 参数检查
        ErrorAssert.notNull(roleId, "Role id can not be null");
        // 查找原有功能
        List<Long> prevFuncIds = roleFunctionRepository.findFunctionIds(roleId);
        // 获取需要添加的功能
        List<Long> funcsToAdd = notContained(prevFuncIds, functionIds);
        // 获取需要删除的功能
        List<Long> funcsToReduce = notContained(functionIds, prevFuncIds);
        // 执行添加
        addAllFuncs(roleId, funcsToAdd);
        // 执行删除
        reduceAllFuncs(roleId, funcsToReduce);
    }

    /**
     * 添加功能
     * @param roleId
     *          角色Id
     * @param funcsToAdd
     *          待添加功能
     */
    private void addAllFuncs(Integer roleId, List<Long> funcsToAdd) {
        if (roleId == null || CollectionUtils.isEmpty(funcsToAdd)) return;
        List<RoleFunction> list = new ArrayList<>();
        funcsToAdd.forEach(funcId -> {
            list.add(new RoleFunction(roleId, funcId));
        });
        roleFunctionRepository.saveAll(list);
    }

    private void reduceAllFuncs(Integer roleId, List<Long> funcsToReduce) {
        if (roleId == null || CollectionUtils.isEmpty(funcsToReduce)) return;
        funcsToReduce.forEach(funcId -> {
            roleFunctionRepository.deleteByRoleIdAndFunctionId(roleId, funcId);
        });
    }

    private List<Long> notContained(List<Long> source, List<Long> candidates) {
        if (CollectionUtils.isEmpty(source)) return candidates;
        if (CollectionUtils.isEmpty(candidates)) return null;
        List<Long> result = new ArrayList<>();
        candidates.forEach(id -> {
            if (!source.contains(id)) result.add(id);
        });
        return result;
    }

    @Override
    public List<Long> getFuncIds(Integer roleId) {
        // 参数检查
        ErrorAssert.notNull(roleId, "Role id can not be null");
        //
        return roleFunctionRepository.findFunctionIds(roleId);
    }
}
